'''
@author: Aurelien Deharbe


This file is part of Cute-Server.

Cute-Server is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Cute-Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Cute-Server.  If not, see <http://www.gnu.org/licenses/>.
'''

from cclientdata import CClientData
from csessiondata import CSessionData
import re
import select
import socket

def cserver(_port):
    
    CSessionData.port = _port
    
    # compiling regexps
    re_new = re.compile(r'QSSessionNew\(([a-z0-9]+)\)')
    re_old = re.compile(r'QSSessionJoin\(([a-z0-9]+)\)')
    re_prt = re.compile(r'QSSessionPort\(([1-9][0-9]*)\)')
    
    # opening server connection socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.bind(('', _port))
    sock.listen(5)
    
    # initializing variables
    sessions = {} # dic sessid:str -> session:QSessionData
    clients  = {} # dic socket:socket -> client:QClientData
    
    # list for select
    rlist = [sock]
    
    while True:
        ready = select.select(rlist, [], [])
        
        for rs in ready[0]:
            
            # if rs is the server socket,
            # there is a new connection
            if rs == sock:
                cli = sock.accept()
                rlist.append(cli[0])
                print "[QServer] connection from " + str(cli[1])
                clients[cli[0]] = CClientData(cli[1][0])
                continue
            
            # read the command on the socket
            try:
                cmd = rs.recv(256)
                cmd = cmd.strip()
            except socket.error:
                cmd = None
            
            # if empty command, client disconnection
            if not cmd:
                try:
                    name = str(rs.getpeername())
                except socket.error:
                    name = "unknown client"
                print "[QServer] deconnexion of " + name
                rlist.remove(rs)
                rs.close()
                clients[rs].closeSessions()
                for sessid, sessiondata in sessions.items():
                    if sessiondata.isDestroyed():
                        del sessions[sessid]
                del clients[rs]
                continue
            
            # command matches QSSessionNew(_) ?
            res = re_new.match(cmd)
            if res:
                sessid = res.group(1)
                if sessid in sessions.keys():
                    # there is already a session with this name
                    rs.send("error\n")
                    continue
                # instantiating the session
                session = CSessionData(sessid)
                if not clients[rs].openSession(session):
                    rs.send("error\n")
                else:
                    sessions[sessid] = session
                    rs.send("ok\n")
                continue
            
            # command matches QSSessionJoin(_) ?
            res = re_old.match(cmd)
            if res:
                sessid = res.group(1)
                if sessid not in sessions.keys():
                    # there is no session with this name
                    rs.send("error\n")
                    continue
                print "[QServer] a client join session " + sessid
                # getting the session
                session = sessions[sessid]
                if not clients[rs].openSession(session):
                    rs.send("error\n")
                else:
                    rs.send("ok\n")
                continue
            
            # command matches QSSessionPort(_) ?
            res = re_prt.match(cmd)
            if res:
                client_port = res.group(1)
                if not clients[rs].sessionPort(client_port):
                    rs.send("error\n")
                else:
                    rs.send("ok\n")
                continue
            
            # command not known
            rs.send("error\n")



if __name__ == '__main__':
    print "Please use the cuteserver script to run it"
